package com.ccx.demo.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import com.ccx.demo.business.user.cache.ITabRoleCache;
import com.ccx.demo.business.user.cache.ITabUserCache;
import com.ccx.demo.business.user.entity.TabRole;
import com.ccx.demo.business.user.entity.TabUser;
import com.ccx.demo.open.auth.cache.TokenCache;
import com.support.mvc.entity.base.AppCacheUnit;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.ehcache.PersistentCacheManager;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.spi.serialization.Serializer;
import org.ehcache.spi.serialization.SerializerException;
import org.redisson.api.RedissonClient;
import org.redisson.spring.cache.CacheConfig;
import org.redisson.spring.cache.RedissonSpringCacheManager;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

import static com.alibaba.fastjson.serializer.SerializerFeature.IgnoreNonFieldGetter;

/**
 * <pre>
 * Spring 缓存配置:
 *   开发环境使用 ehcache.xml
 *     参考：
 *       https://www.cnblogs.com/Sicwen/p/10588047.html
 *       https://blog.csdn.net/weixin_30722589/article/details/98150575
 * </pre>
 *
 * @author 谢长春
 */
@Slf4j
@EnableCaching
@Configuration(proxyBeanMethods = false)
@RequiredArgsConstructor
@ConfigurationProperties(prefix = "spring.app.cache")
public class CacheConfiguration {
    private final ApplicationContext applicationContext;
    private final RedissonClient redissonClient;

    /**
     * ehcache 磁盘持久化存储目录
     */
    private String diskStore;

    /**
     * TokenCache.CACHE_TOKEN 缓存配置
     */
    @Setter
    @Getter
    private AppCacheUnit token;
    /**
     * ITabUserCache.CACHE_LOGIN 缓存配置
     */
    @Setter
    @Getter
    private AppCacheUnit login;
    /**
     * ITabUserCache.CACHE_ROW_BY_ID 缓存配置
     */
    @Setter
    @Getter
    private AppCacheUnit tabUser;
    /**
     * ITabRoleCache.CACHE_ROW_BY_ID 缓存配置
     */
    @Setter
    @Getter
    private AppCacheUnit tabRole;

    @Bean
    public CommandLineRunner printCacheConfigurationCommandLineRunner() {
        return args -> {
            new LinkedHashMap<String, AppCacheUnit>() {{
                put("token", token);
                put("login", login);
                put("tabUser", tabUser);
                put("tabRole", tabRole);
            }}.forEach((key, unit) -> {
                log.info(
                        "\nspring.app.cache.{}.expired : {}"
                                + "\nspring.app.cache.{}.heap : {}"
                                + "\nspring.app.cache.{}.offheap : {}"
                                + "\nspring.app.cache.{}.disk : {}"
                        , key, unit.getExpired().toMillis()
                        , key, unit.getHeap()
                        , key, unit.getOffheap()
                        , key, unit.getDisk()
                );
            });
        };
    }
//    @ConditionalOnExpression("'local'.equals('${spring.app.env}')")
//    @Bean(destroyMethod = "close")
//    public javax.cache.CacheManager ehPersistentCacheManager() {
//        CacheManagerBuilder<PersistentCacheManager> cacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder()
//                .with(CacheManagerBuilder.persistence(Paths.get(diskStore).toFile()));
//        for (Map.Entry<String, ICacheConfig> entry : applicationContext.getBeansOfType(ICacheConfig.class).entrySet()) {
//            log.info("动态组装【{}】模块缓存", entry.getKey());
//            cacheManagerBuilder = entry.getValue().join(cacheManagerBuilder);
//        }
//        final PersistentCacheManager persistentCacheManager = cacheManagerBuilder
//                .withCache(TokenCache.CACHE_TOKEN, CacheConfigurationBuilder
//                        .newCacheConfigurationBuilder(Long.class, TokenCache.class, ResourcePoolsBuilder.newResourcePoolsBuilder()
//                                .heap(token.getHeap(), EntryUnit.ENTRIES)
//                                .offheap(token.getOffheap(), MemoryUnit.MB)
//                                .disk(token.getDisk(), MemoryUnit.MB, true)
//                        )
//                        .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(token.getExpired()))
//                        .withValueSerializer(new FastJsonEhcacheSerializer<>(TokenCache.class))
//                )
//                .withCache(ITabUserCache.CACHE_ROW_BY_ID, CacheConfigurationBuilder
//                        .newCacheConfigurationBuilder(Long.class, TabUser.class, ResourcePoolsBuilder.newResourcePoolsBuilder()
//                                .heap(tabUser.getHeap(), EntryUnit.ENTRIES)
//                                .offheap(tabUser.getOffheap(), MemoryUnit.MB)
//                                .disk(tabUser.getDisk(), MemoryUnit.MB, true)
//                        )
//                        .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(tabUser.getExpired()))
//                        .withValueSerializer(new FastJsonEhcacheSerializer<>(TabUser.class))
//                )
//                .withCache(ITabUserCache.CACHE_LOGIN, CacheConfigurationBuilder
//                        .newCacheConfigurationBuilder(String.class, TabUser.class, ResourcePoolsBuilder.newResourcePoolsBuilder()
//                                .heap(login.getHeap(), EntryUnit.ENTRIES)
//                                .offheap(login.getOffheap(), MemoryUnit.MB)
//                                .disk(login.getDisk(), MemoryUnit.MB, true)
//                        )
//                        .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(login.getExpired()))
//                        .withValueSerializer(new FastJsonEhcacheSerializer<>(TabUser.class))
//                )
//                .withCache(ITabRoleCache.CACHE_ROW_BY_ID, CacheConfigurationBuilder
//                        .newCacheConfigurationBuilder(Long.class, TabRole.class, ResourcePoolsBuilder.newResourcePoolsBuilder()
//                                .heap(tabRole.getHeap(), EntryUnit.ENTRIES)
//                                .offheap(tabRole.getOffheap(), MemoryUnit.MB)
//                                .disk(tabRole.getDisk(), MemoryUnit.MB, true)
//                        )
//                        .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(tabRole.getExpired()))
//                        .withValueSerializer(new FastJsonEhcacheSerializer<>(TabRole.class))
//                )
////                    .withCache(ITabUserCache.CACHE_ROW_BY_ID, CacheConfigurationBuilder
////                            .newCacheConfigurationBuilder(Long.class, TabUser.class, ResourcePoolsBuilder.newResourcePoolsBuilder()
////                                    .heap(100, EntryUnit.ENTRIES)
////                                    .offheap(1, MemoryUnit.MB)
////                                    .disk(100, MemoryUnit.MB, true)
////                            )
////                            .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofDays(10)))
////                            .withService(new OffHeapDiskStoreConfiguration(2)) // 磁盘分片数量
////                            .withValueSerializer(new Serializer<TabUser>() {
////                                @Override
////                                public ByteBuffer serialize(TabUser object) throws SerializerException {
////                                    return ByteBuffer.wrap(JSON.toJSONBytes(object));
////                                }
////
////                                @Override
////                                public TabUser read(ByteBuffer binary) throws SerializerException {
////                                    return JSON.parseObject(binary.array(), TabUser.class);
////                                }
////
////                                @Override
////                                public boolean equals(TabUser object, ByteBuffer binary) throws SerializerException {
////                                    boolean equals = binary.equals(serialize(object));
////                                    binary.position(binary.limit());
////                                    return equals;
////                                }
////                            })
////                    )
//                .build();
//        final CachingProvider cachingProvider = Caching.getCachingProvider();
//        final EhcacheCachingProvider ehcacheCachingProvider = (EhcacheCachingProvider) cachingProvider;
//        final DefaultConfiguration configuration = new DefaultConfiguration(persistentCacheManager.getRuntimeConfiguration());
//        return ehcacheCachingProvider.getCacheManager(ehcacheCachingProvider.getDefaultURI(), configuration);
//    }
//
//    /**
//     * 开发环境启用 ehcache
//     */
//    @ConditionalOnExpression("'local'.equals('${spring.app.env}')")
//    @Bean(value = "cacheManager")
//    public CacheManager ehCacheManager(javax.cache.CacheManager ehPersistentCacheManager) {
//        return new JCacheCacheManager(ehPersistentCacheManager);
////        {
////            CachingProvider cachingProvider = Caching.getCachingProvider();
////            EhcacheCachingProvider ehcacheCachingProvider = (EhcacheCachingProvider) cachingProvider;
////            DefaultConfiguration configuration = new DefaultConfiguration(ehcacheCachingProvider.getDefaultClassLoader(),
////                    new DefaultPersistenceConfiguration(new File("")));
////            javax.cache.CacheManager cacheManager = ehcacheCachingProvider.getCacheManager(ehcacheCachingProvider.getDefaultURI(), configuration);
////            return new JCacheCacheManager(cacheManager);
////        }
//
////        CacheManager cacheManager = ehcacheProvider.getCacheManager(ehcacheProvider.getDefaultURI(), configuration);
////        org.ehcache.config.Configuration threeTieredCache = CacheManagerBuilder.newCacheManagerBuilder()
////                .with(CacheManagerBuilder.persistence(new File("")))
////                .withCache("threeTieredCache",
////                        CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
////                                ResourcePoolsBuilder.newResourcePoolsBuilder()
////                                        .heap(10, EntryUnit.ENTRIES)
////                                        .offheap(1, MemoryUnit.MB)
////                                        .disk(20, MemoryUnit.MB, true))
////                                .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(20)))
////                ).build(false)
////                .getRuntimeConfiguration();
//////        DefaultConfiguration defaultConfiguration = new DefaultConfiguration(threeTieredCache);
////        EhcacheManager ehcacheManager = new EhcacheManager(threeTieredCache);
////        new CacheProperties.JCache
////        return ehcacheManager;
////        return CacheManagerBuilder.newCacheManagerBuilder()
////                .with(CacheManagerBuilder.persistence(new File("/app/files/ehcache")))
////                .withCache(ITabUserCache.CACHE_LOGIN, CacheConfigurationBuilder
////                        .newCacheConfigurationBuilder(Long.class, TabUser.class, ResourcePoolsBuilder.newResourcePoolsBuilder()
////                                .heap(100, EntryUnit.ENTRIES)
////                        )
////                )
////                .build()
////               ;
//    }

    /**
     * 启用 redis 缓存
     */
    @ConditionalOnMissingBean(RedissonClient.class)
    @Bean("cacheManager")
    public CacheManager redisCacheManager(final RedisConnectionFactory redisConnectionFactory) {
//        final RedisSerializationContext.SerializationPair<String> serializeKeys = RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer());
//        Jackson2JsonRedisSerializer<TabUser> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<TabUser>(TabUser.class) {
//            @Override
//            public void setObjectMapper(ObjectMapper objectMapper) {
//                super.setObjectMapper(objectMapper);
//            }
//        };
        final RedisCacheManager.RedisCacheManagerBuilder cacheManagerBuilder = RedisCacheManager.builder(redisConnectionFactory);
        applicationContext.getBeansOfType(ICacheConfig.class).forEach((moduleName, config) -> config.join(cacheManagerBuilder));
        return cacheManagerBuilder
                .withCacheConfiguration(TokenCache.CACHE_TOKEN, RedisCacheConfiguration.defaultCacheConfig()
                                .entryTtl(token.getExpired()) // 设置过期时间
                                .disableCachingNullValues() // 禁止缓存 null 值
//                               .serializeKeysWith(serializeKeys) // 设置 key 序列化
//                                // 设置 value 序列化
//                                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new Jackson2JsonRedisSerializer<>(TabUser.class)))
                                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new CustomFastJsonRedisSerializer<>(TokenCache.class)))
                )
                .withCacheConfiguration(ITabUserCache.CACHE_LOGIN, RedisCacheConfiguration.defaultCacheConfig()
                                .entryTtl(login.getExpired()) // 设置过期时间
//                        .disableCachingNullValues() // 禁止缓存 null 值
                                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new CustomFastJsonRedisSerializer<>(TabUser.class)))
                )
                .withCacheConfiguration(ITabUserCache.CACHE_ROW_BY_ID, RedisCacheConfiguration.defaultCacheConfig()
                        .entryTtl(tabUser.getExpired()) // 设置过期时间
                        .disableCachingNullValues() // 禁止缓存 null 值
                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new CustomFastJsonRedisSerializer<>(TabUser.class)))
                )
                .withCacheConfiguration(ITabRoleCache.CACHE_ROW_BY_ID, RedisCacheConfiguration.defaultCacheConfig()
                        .entryTtl(tabRole.getExpired()) // 设置过期时间
                        .disableCachingNullValues() // 禁止缓存 null 值
                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new CustomFastJsonRedisSerializer<>(TabRole.class)))
                )
                .build();
    }

    /**
     * 启用 redisson 缓存
     * https://www.bookstack.cn/read/redisson-wiki-zh/spilt.2.14.-%E7%AC%AC%E4%B8%89%E6%96%B9%E6%A1%86%E6%9E%B6%E6%95%B4%E5%90%88.md
     */
    @ConditionalOnBean(RedissonClient.class)
    @Bean("cacheManager")
    public CacheManager redissonCacheManager(final RedissonClient redissonClient) {
        final HashMap<String, CacheConfig> cacheMap = new HashMap<String, CacheConfig>(10) {{
            put(TokenCache.CACHE_TOKEN, new CacheConfig(token.getExpired().toMillis(), token.getExpired().toMillis() / 2));
            put(ITabUserCache.CACHE_LOGIN, new CacheConfig(login.getExpired().toMillis(), login.getExpired().toMillis() / 2));
            put(ITabUserCache.CACHE_ROW_BY_ID, new CacheConfig(tabUser.getExpired().toMillis(), tabUser.getExpired().toMillis() / 2));
            put(ITabRoleCache.CACHE_ROW_BY_ID, new CacheConfig(tabRole.getExpired().toMillis(), tabRole.getExpired().toMillis() / 2));
        }};
        // 连接其他模块的缓存
        applicationContext.getBeansOfType(ICacheConfig.class).forEach((moduleName, config) -> cacheMap.putAll(config.join()));
        return new RedissonSpringCacheManager(redissonClient, cacheMap);
    }

    /**
     * 使用 FastJson 自定义 ehcache 缓存序列化
     *
     * @param <T>
     */
    public static class FastJsonEhcacheSerializer<T> implements Serializer<T> {
        private FastJsonConfig fastJsonConfig = new FastJsonConfig();
        private Class<T> type;

        private FastJsonEhcacheSerializer() {
        }

        public FastJsonEhcacheSerializer(Class<T> type) {
            this.type = type;
            this.fastJsonConfig.setSerializerFeatures(IgnoreNonFieldGetter);
        }

        public FastJsonConfig getFastJsonConfig() {
            return fastJsonConfig;
        }

        public void setFastJsonConfig(FastJsonConfig fastJsonConfig) {
            this.fastJsonConfig = fastJsonConfig;
        }

        @Override
        public ByteBuffer serialize(T object) throws SerializerException {
            if (object == null) {
                return ByteBuffer.wrap(new byte[0]);
            }
            return ByteBuffer.wrap(JSON.toJSONBytes(
                    fastJsonConfig.getCharset(),
                    object,
                    fastJsonConfig.getSerializeConfig(),
                    fastJsonConfig.getSerializeFilters(),
                    fastJsonConfig.getDateFormat(),
                    JSON.DEFAULT_GENERATE_FEATURE,
                    fastJsonConfig.getSerializerFeatures()
            ));
        }

        @Override
        public T read(ByteBuffer binary) throws SerializerException {
            if (Objects.isNull(binary)) return null;
            final byte[] bytes = binary.array();
            if (bytes.length == 0) return null;
            return JSON.parseObject(
                    bytes,
                    fastJsonConfig.getCharset(),
                    type,
                    fastJsonConfig.getParserConfig(),
                    fastJsonConfig.getParseProcess(),
                    JSON.DEFAULT_PARSER_FEATURE,
                    fastJsonConfig.getFeatures()
            );
        }

        @Override
        public boolean equals(T object, ByteBuffer binary) throws SerializerException {
            boolean equals = Objects.equals(binary, serialize(object));
            binary.position(binary.limit());
            return equals;
        }
    }

    public static class CustomFastJsonRedisSerializer<T> extends FastJsonRedisSerializer<T> {
        public CustomFastJsonRedisSerializer(Class<T> type) {
            super(type);
            getFastJsonConfig().setSerializerFeatures(IgnoreNonFieldGetter);
        }

//        @Override
//        public FastJsonConfig getFastJsonConfig() {
//            final FastJsonConfig fastJsonConfig = super.getFastJsonConfig();
//            fastJsonConfig.setSerializerFeatures(IgnoreNonFieldGetter);
//            return fastJsonConfig;
//        }
    }

    /**
     * 模块分离时，用于连接其他模块的缓存
     * <pre>
     * import org.ehcache.PersistentCacheManager;
     * import org.ehcache.config.builders.CacheConfigurationBuilder;
     * import org.ehcache.config.builders.CacheManagerBuilder;
     * import org.ehcache.config.builders.ResourcePoolsBuilder;
     * import org.ehcache.config.units.EntryUnit;
     * import org.ehcache.config.units.MemoryUnit;
     * import org.springframework.data.redis.cache.RedisCacheConfiguration;
     * import org.springframework.data.redis.cache.RedisCacheManager;
     * import org.springframework.data.redis.serializer.RedisSerializationContext;
     * import org.springframework.stereotype.Component;
     *
     * import java.time.Duration;
     *
     * \@Component
     * public class ModuleCacheConfig implements CacheConfig.ICacheConfig {
     *     \@Override
     *     public CacheManagerBuilder<PersistentCacheManager> join(CacheManagerBuilder<PersistentCacheManager> cacheManagerBuilder) {
     *         return cacheManagerBuilder
     *                 .withCache(ICache.CACHE_ROW_BY_ID, CacheConfigurationBuilder
     *                         .newCacheConfigurationBuilder(String.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder()
     *                                 .heap(10, EntryUnit.ENTRIES)
     *                                 .disk(100, MemoryUnit.MB, true)
     *                         )
     *                 );
     *     }
     *
     *     \@Override
     *     public void join(RedisCacheManager.RedisCacheManagerBuilder cacheManagerBuilder) {
     *         cacheManagerBuilder.withCacheConfiguration(ICache.CACHE_ROW_BY_ID, RedisCacheConfiguration.defaultCacheConfig()
     *                 .entryTtl(Duration.ofDays(30)) // 设置过期时间
     *                 .prefixCacheNameWith(ICache.CACHE_ROW_BY_ID.concat(":")) // 设置缓存前缀
     *                 .disableCachingNullValues() // 禁止缓存 null 值
     *                 .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new CacheConfig.CustomFastJsonRedisSerializer<>(String.class)))
     *         );
     *     }
     * }
     * </pre>
     */
    public interface ICacheConfig {
        /**
         * EHCache 连接其他模块的缓存配置
         *
         * @param cacheManagerBuilder {@link CacheManagerBuilder<PersistentCacheManager>}
         * @return CacheManagerBuilder<PersistentCacheManager>
         */
        CacheManagerBuilder<PersistentCacheManager> join(CacheManagerBuilder<PersistentCacheManager> cacheManagerBuilder);

        /**
         * Redisson 连接其他模块的缓存配置
         *
         * @return Map<String, CacheConfig>
         */
        Map<String, CacheConfig> join();

        /**
         * Redis 连接其他模块的缓存配置
         *
         * @param cacheManagerBuilder {@link RedisCacheManager.RedisCacheManagerBuilder}
         */
        void join(RedisCacheManager.RedisCacheManagerBuilder cacheManagerBuilder);

//        /**
//         * Redisson 连接其他模块的缓存配置
//         *
//         * @return Map<String, org.redisson.spring.cache.CacheConfig>
//         */
//        Map<String, CacheConfig> join();
    }

//    private static final Set<String> cacheNames = Sets.newHashSet(
//            TokenCache.CACHE_TOKEN
//            , ITabUserCache.CACHE_ROW_BY_ID
//            , ITabUserCache.CACHE_LOGIN
//            , ITabRoleCache.CACHE_ROW_BY_ID
//    );
//    /**
//     * 记录所有缓存模块版本号
//     */
//    private final String VERSION = "VERSION";
//                .withCache(VERSION, CacheConfigurationBuilder
//                        .newCacheConfigurationBuilder(String.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder()
//                                .heap(10, EntryUnit.ENTRIES)
//                                .disk(100, MemoryUnit.MB, true)
//                        )
//                )
//
//                .withCacheConfiguration(VERSION, RedisCacheConfiguration.defaultCacheConfig()
//                        .prefixCacheNameWith(VERSION.concat(":")) // 设置缓存前缀
//                        .disableCachingNullValues() // 禁止缓存 null 值
//                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new FastJsonRedisSerializer<>(String.class)))
//                )
//    @Override
//    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
//        final CacheManager cacheManager = applicationContext.getBean("cacheManager", CacheManager.class);
//        log.info("检查缓存版本号：{}", appConfig.getVersion());
//        final Set<String> clearCacheNames = Sets.newHashSet(
//                // 这里配置本次上线需要清除的缓存 **********************************************************************
//                TokenCache.CACHE_TOKEN
//                , ITabUserCache.CACHE_ROW_BY_ID
//                , ITabUserCache.CACHE_LOGIN
////                , ITabRoleCache.CACHE_ROW_BY_ID
//        );
//        final Cache versionCache = Objects.requireNonNull(cacheManager.getCache(VERSION), "未配置【VERSION】管理缓存版本号");
//        for (String name : cacheNames) {
//            final Cache cache = Objects.requireNonNull(cacheManager.getCache(name), "未配置缓存：".concat(name));
//            final String cacheVersion = Optional.ofNullable(versionCache.get(name)).map(Cache.ValueWrapper::get).map(Object::toString).orElse(null);
//            log.info("{}：{} => {}", name, cacheVersion, appConfig.getVersion());
//            if (!Objects.equals(appConfig.getVersion(), cacheVersion)) {
//                if (clearCacheNames.contains(name)) {
//                    // 版本号比匹配，且需要清除的缓存， 执行清除动作
//                    cache.clear();
//                    log.info("清除缓存：{}", name);
//                }
//                versionCache.put(name, appConfig.getVersion());
//            }
//        }
//    }

}
